#include "Utility.h"

void display(void)
{	

	/************************************************************************/
	/*						   Shadow Pass (Light)                          */
	/************************************************************************/

	UpdateMatrix();	

	TransposeMatrix(ProjectionLightOgl,ProjectionLight);
	TransposeMatrix(ObjectToLightOgl,ObjectToLight);

	ShadowBuffer[LIGHTSPACE].FBOActivate();

	glClearColor(0,0,0,0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glViewport(0, 0, ImageWidth*2, ImageHeight*2);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glLoadMatrixf( ProjectionLightOgl );
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glLoadMatrixf(ObjectToLightOgl);

	glGetFloatv(GL_PROJECTION_MATRIX,LightProjectMatrix);
	glGetFloatv(GL_MODELVIEW_MATRIX,LightMVMatrix);	

	drawModel();

	ShadowBuffer[LIGHTSPACE].FBODeactivate();

	/************************************************************************/
	/*						   Shadow Pass (Camera)                         */
	/************************************************************************/

	ShadowBuffer[CAMERASPACE].FBOActivate();

	glClearColor(0,0,0,0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glViewport(0, 0, ImageWidth*2, ImageHeight*2);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f,(GLfloat) ImageWidth / (GLfloat)ImageHeight , 0.5f, -70.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glLoadMatrixf(MVMatrix);

	drawModel();

	ShadowBuffer[CAMERASPACE].FBODeactivate();

	/************************************************************************/
	/*                          Irradiance Pass                             */
	/************************************************************************/

	IrradianceBuffer.FBOActivate();

	glDepthFunc(GL_LESS);
	glEnable(GL_DEPTH_TEST);

	UpdateMatrix();
	TransposeMatrix(ProjectiveLightOgl,ProjectiveLight);

	glClearColor(0,0,0,1);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f,(GLfloat) ImageWidth / (GLfloat)ImageHeight , 0.5f, -70.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glViewport(0, 0, ImageWidth, ImageHeight);

	glLoadMatrixf(MVMatrix);

	glGetFloatv(GL_PROJECTION_MATRIX,ProjectMatrix);

	vIrradiance.bind();
	fIrradiance.bind();

	drawModel();

	vIrradiance.release();
	fIrradiance.release();

	IrradianceBuffer.FBODeactivate();

	/************************************************************************/
	/*                             Blur Pass                                */
	/************************************************************************/

	float gVariance[BLURSTEP] = {0.036, 0.14, 0.91, 7.0};
	float gWidth[BLURSTEP];

	gWidth[0] = 0;
	for(int i=1; i<BLURSTEP; i++)
	{
		float v = gVariance[i] - gVariance[i-1];
		gWidth[i] = sqrtf(v);
	}

	for(int i=0; i<BLURSTEP; i++){

		InterBuffer.FBOActivate();

		gaussianStretch = ShadowBuffer[CAMERASPACE].framebuffer.texID[0];

		if(i==0)
			gaussianIrradiance = IrradianceBuffer.framebuffer.texID[0];
		else
			gaussianIrradiance = GaussianBuffer[i-1].framebuffer.texID[0];

		gaussianWidth = gWidth[i];

		vGaussianU.bind();
		fGaussianU.bind();

		drawQuad();

		vGaussianU.release();
		fGaussianU.release();	

		InterBuffer.FBODeactivate();

		GaussianBuffer[i].FBOActivate();

		gaussianStretch = ShadowBuffer[CAMERASPACE].framebuffer.texID[0];
		gaussianIrradiance = InterBuffer.framebuffer.texID[0];
		gaussianWidth = gWidth[i];

		vGaussianV.bind();
		fGaussianV.bind();

		drawQuad();

		vGaussianV.release();
		fGaussianV.release();	

		GaussianBuffer[i].FBODeactivate();

	}


#if 1
	glClearColor(0,0,0,1);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	vRender.bind();
	fRender.bind();

	drawQuad();

	vRender.release();
	fRender.release();
#else
	glClearColor(0,0,0,0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, ImageWidth, 0.0, ImageHeight);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glViewport(0, 0, ImageWidth, ImageHeight);

	glPolygonMode(GL_FRONT,GL_FILL);

	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D,IrradianceBuffer.framebuffer.texID[2]);

	glBegin(GL_QUADS);
	glTexCoord2f(0.0, 0.0); 
	glVertex2f(0.0, 0.0);
	glTexCoord2f(1.0, 0.0); 
	glVertex2f(ImageWidth, 0.0);
	glTexCoord2f(1.0, 1.0); 
	glVertex2f(ImageWidth, ImageHeight);
	glTexCoord2f(0.0, 1.0); 
	glVertex2f(0.0, ImageHeight);
	glEnd();

	glDisable(GL_TEXTURE_2D);
#endif
	

	glutSwapBuffers(); 
	glutPostRedisplay();

}


int main(int argc, char **argv)
{
	//objData = new objLoader();
	//objData->load("what.obj");

	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(ImageWidth, ImageHeight);
	glutCreateWindow("FLIP");
	LoadTexture();
	InitGL();
	InitCG();
	InitFrameBuffer();
	InitModel();
	LoadShader();
	InitShader();
	glutDisplayFunc(display);

	glui=GLUI_Master.create_glui("Control");

	GLUI_Rollout *Rotation=glui->add_rollout("Rotation");
	GLUI_Rotation *ro=glui->add_rotation_to_panel(Rotation,"World Rotation",(float*)obj_rot);
	ro->reset();
	GLUI_Rotation *rl=glui->add_rotation_to_panel(Rotation,"Light Rotation",(float*)lig_rot);
	rl->reset();

	GLUI_Rollout *Translation=glui->add_rollout("Translation");
	GLUI_Translation *tc=glui->add_translation_to_panel(Translation,"Camera Translation",GLUI_TRANSLATION_Z,&(eye_position[2]));
	tc->set_speed(-0.5);
	tc->set_z(eye_position[2]);

	GLUI_Translation *tl=glui->add_translation_to_panel(Translation,"Light Translation",GLUI_TRANSLATION_Z,&(light_distance));
	tl->set_speed(0.5);
	tl->set_z(light_distance);

	//printf("%d\n",objData->textureCount);

	glutMainLoop();


	return 0;

}
